package com.pd.ds.tree;

import java.io.Serializable;

public class LeastRecentlyOccoured<T extends Comparable<T>> implements Serializable {

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("LeastRecentlyOccoured [");
		Node<T> temp = head;
		while (temp != null) {
			builder.append("Node: ").append(temp);
			temp = temp.getNext();
		}

		builder.append("]");

		return builder.toString();
	}

	public static void main(String[] args) {
		LeastRecentlyOccoured<String> leastRecentlyOccouredMessage = new LeastRecentlyOccoured<String>();

		// LinkedHashSet<String> leastRecentlyOccouredMessage = new
		// LinkedHashSet<String>();

		leastRecentlyOccouredMessage.add("A");
		leastRecentlyOccouredMessage.add("B");
		leastRecentlyOccouredMessage.add("C");
		// leastRecentlyOccouredMessage.remove("A");
		leastRecentlyOccouredMessage.add("A");

		leastRecentlyOccouredMessage.add("A");

		System.out.println(leastRecentlyOccouredMessage);
		// System.out.println(leastRecentlyOccouredMessage.);

	}

	private static final long serialVersionUID = 1L;

	private Node<T> head;
	private Node<T> tail;

	public void add(T data) {

		Node<T> temp = new Node<T>(data);
		if (tail != null && tail.compareTo(temp) == 0) {
			if (tail.getNext() != null) {
				tail.getNext().setPrev(tail.getPrev());
			}
			if (tail.getPrev() != null) {
				tail.getPrev().setNext(tail.getNext());
				tail = tail.getPrev();
			}
		}
		if (head == null) {
			head = temp;
			tail = temp;
		} else {
			temp.setNext(head);
			head.setPrev(temp);
			head = temp;
		}
	}

	private void remove(Node<T> node) {

		if (null != node) {
			if (node.getPrev() != null) {
				node.getPrev().setNext(node.getNext());
			}
			if (node.getNext() != null) {
				node.getNext().setPrev(node.getPrev());
			}
		}
	}

	public T lrom() {
		if (tail == null) {
			throw new RuntimeException("No message added.");
		}
		return tail.getData();
	}

	private class Node<T extends Comparable<T>> implements Comparable<Node<T>> {
		private T data;
		private Node<T> next;
		private Node<T> prev;

		public Node<T> getPrev() {
			return prev;
		}

		public void setPrev(Node<T> prev) {
			this.prev = prev;
		}

		public Node(T data) {
			this.data = data;
			this.next = null;
		}

		public T getData() {
			return data;
		}

		public Node<T> getNext() {
			return next;
		}

		public void setNext(Node<T> next) {
			this.next = next;
		}

		@Override
		public int compareTo(Node<T> o) {
			return this.data.compareTo(o.getData());
		}

		@Override
		public String toString() {
			StringBuilder builder = new StringBuilder();
			builder.append("Node [data=");
			builder.append(data);
			builder.append("]");
			return builder.toString();
		}
	}
}
